﻿using System;
using System.Linq;
using FlatRedBall.Graphics;
using FlatRedBall.Input;
using Microsoft.Xna.Framework;
using Rvz.Game.Main.Common;
using Rvz.Game.Main.Inputs;
using Rvz.Game.Main.Rules;
using Rvz.Game.Main.Rules.Waves;

namespace Rvz.Game.Main.State
{
    public class GameState
    {
        public GraphicsDeviceManager GraphicsDeviceManager { get; protected set; }
        public string ContentManagerName { get; protected set; }
        private readonly Text _text;

        public GameState(GraphicsDeviceManager graphicsDeviceManager, string contentManagerName)
        {
            GraphicsDeviceManager = graphicsDeviceManager;
            ContentManagerName = contentManagerName;

            NewGame();

            //TODO: A real UI/HUD overlay ref: http://www.flatredball.com/frb/docs/index.php?title=Glue:Tutorials:Using_Layers
            _text = TextManager.AddText(string.Empty);
            _text.SetColor(0, 0, 0);
            _text.X = Helper.RightXCoordinate - 20;
            _text.Y = Helper.TopYCoordinate - 1;
        }

        public void NewGame()
        {
            RemainingLives = 3;
            Time = 90;
            Score = 0;

            if (PlayerState != null)
            { PlayerState.Destroy(); }
            PlayerState = new PlayerState();

            if (WaveState != null)
            { WaveState.Destroy(); }
            WaveState = new WaveState(new WaveLevelOne());
        }

        public int Time { get; set; }
        public Int64 Score { get; set; }
        public int RemainingLives { get; set; }
        public WaveState WaveState { get; set; }
        public PlayerState PlayerState { get; set; }

        public void Update(GameTime gameTime)
        {
            var player1InputDevice = InputManager.Xbox360GamePads[0].IsConnected
                ? (IRationalizedInputDevice)new RationalizedGamePadInput(InputManager.Xbox360GamePads[0], 2)
                : (IRationalizedInputDevice)new RationalizedPcInput(InputManager.Keyboard, InputManager.Mouse);

            var robot = PlayerState.Robot;
            robot.HandleUpdateInput(this, player1InputDevice, gameTime);
            robot.HandleUpdate(this, gameTime);

            WaveState.ActiveZombies.ForEach(x => x.HandleUpdate(this, gameTime));

            ProjectileEngine.ProcessRules(this);
            WaveManager.ProcessWaveEvents(this);

            UpdateHUD(gameTime);

            if (robot.IsDead())
            { EndGame(); }
        }

        private void UpdateHUD(GameTime gameTime)
        {
            _text.DisplayText = string.Format("{0} - {1} killed out of {2}",
                WaveState.WaveLevel.LevelDescription,
                WaveState.FraggedZombies.Count(),
                WaveState.WaveLevel.TotalZombiesOnLevel);
        }

        public void EndGame()
        {
            NewGame();
        }
    }
}
